<?php
namespace App\Services;

use App\Events\RechargeBillRecord;
use App\Lib\BCMathLib;
use App\Lib\SystemNumber;
use App\Models\PlatUser;
use App\Models\RechargeGroupPayment;
use App\Models\RechargeIf;
use App\Models\RechargeIfPms;
use App\Models\RechargeOrder;
use App\Models\RechargeSplitMode;
use App\Repositories\Eloquent\AssetCountEloquent;
use App\Repositories\Eloquent\RechargeOrderRepositoryEloquent;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;
use Ramsey\Uuid\Uuid;

class RechargeOrderService
{
    protected $platuserService;
    protected $splitModeService;
    protected $orderRepository;
    protected $assetCount;
    protected $bcLib;

    public function __construct(PlatUserService $platUserService,
                                RechargeSplitModeService $rechargeSplitModeService,
                                RechargeOrderRepositoryEloquent $rechargeOrderRepositoryEloquent,
                                AssetCountEloquent $assetCountEloquent,
                                BCMathLib $BCMathLib)
    {
        $this->platuserService = $platUserService;
        $this->splitModeService = $rechargeSplitModeService;
        $this->orderRepository = $rechargeOrderRepositoryEloquent;
        $this->assetCount = $assetCountEloquent;
        $this->bcLib = $BCMathLib;
    }


    public function storeOrder(Request $request,
                               PlatUser $platUser,
                               RechargeGroupPayment $payment,
                               RechargeIf $rechargeIf)
    {
        /**
         * [
         * 'proxy' =>
         * 'business' =>
         * 'proxy_rate' =>
         * 'business_rate' =>
         * 'proxy_settle' =>
         * 'business_settle' =>
         * ]
         */
        $order_amt = $request->input('order_amt');
        $app = $platUser->apps()->where('app_id', $request->input('app_id'))->first();
        $mch_no = $request->input('mch_no');
        $upper = $this->platuserService->getUppersWithSettle($order_amt, $platUser, $payment);
        $plat_no = SystemNumber::getRechargeOrderNumber($request->input('mch_code'));
        $upperIf_rate = RechargeIfPms::where('pm_id', $payment->pm_id)->where('if_id', $rechargeIf->id)->first()->rate;
        $upper_settle = $this->bcLib->getSettleByRate($order_amt, $upperIf_rate);
        $orderInfo = [
            'plat_no' => $plat_no,
            'merchant_no' => $mch_no,
            'uid' => $platUser->id,
            'app_id' => $app->id,
            'pm_id' => $payment->pm_id,
            'order_amt' => $order_amt,
            'order_rate' => $payment->rate,
            'order_settle' => $this->bcLib->getSettleByRate($order_amt, $payment->rate),
            'order_status' => 0,
            'order_data' => $request->all(),
            'upper' => $rechargeIf->id,
            'upper_rate' => $upperIf_rate,
            'upper_settle' => $upper_settle,
            'req_ip' => $request->getClientIp(),
            'settle_day' => $payment->settle_cycle,
            'is_settle' => 0,
//            'settled_at' => Carbon::now()->addDay($payment->settle_cycle)->toDateTimeString(),
            'created_at' => Carbon::now()->toDateTimeString()
        ];
        $orderInfo = $orderInfo + $upper;
        $info = RechargeOrder::create($orderInfo);
        return $info;
    }


    /**
     * @param \App\Models\RechargeOrder $order
     *
     * @return \App\Models\RechargeOrder
     */
    public function updateOrder(RechargeOrder $order)
    {
        $now = Carbon::now();
        $order->order_status = 1;
//        $order->third_no = $third_no;
//        $order->third_notify = $notify_data;
//        $order->third_notify_time += 1;
        $order->updated_at = $now->toDateTimeString();
//        $order->settled_at = $now->addDay($order->settle_day)->toDateTimeString();
        $order->settled_at = Carbon::parse($order->created_at)
            ->addDay($order->settle_day)
            ->startOfDay()
            ->toDateTimeString();
        $order->save();
        return $order;
    }

    /**
     * @param \App\Models\RechargeOrder $order
     * @param array                     $notify_data 异步通知参数
     * @param string                     $third_no   第三方订单号
     *
     * @return \App\Models\RechargeOrder
     */
    public function updateOrderThirdNotify(RechargeOrder $order,
                                              array $notify_data = [],
                                              $third_no='')
    {
        $order->third_no = $third_no;
        $order->third_notify = $notify_data;
        $order->third_notify_time += 1;
        $order->save();
        return $order;
    }

    public function settleOrder(RechargeOrder $rechargeOrder)
    {
        $settle_date = Carbon::parse($rechargeOrder->settled_at)->startOfDay();
        $current_settle = Carbon::now()->gt($settle_date);
        if ($rechargeOrder->settle_day == 0 || $current_settle) {
            if ($this->assetCount->operateAsset($rechargeOrder->uid, 'add', $rechargeOrder->order_settle)) {

                if ($rechargeOrder->proxy)
                    $this->assetCount->operateAsset($rechargeOrder->proxy, 'add', $this->getProxySettle($rechargeOrder));
                if ($rechargeOrder->business)
                    $this->assetCount->operateAsset($rechargeOrder->business, 'add', $this->getBusinessSettle($rechargeOrder));
                $rechargeOrder->is_settle = 1;
                if ($current_settle) {
                    $rechargeOrder->settled_at = Carbon::now()->toDateTimeString();
                }
                $rechargeOrder->save();
            }
            event(new RechargeBillRecord($rechargeOrder));
        } else {
            $this->assetCount->operateAsset($rechargeOrder->uid, 'rechargeFrozen', $rechargeOrder->order_settle);
            if ($rechargeOrder->proxy)
                $this->assetCount->operateAsset($rechargeOrder->proxy, 'rechargeFrozen', $this->getProxySettle($rechargeOrder));
            if ($rechargeOrder->business)
                $this->assetCount->operateAsset($rechargeOrder->business, 'rechargeFrozen', $this->getBusinessSettle($rechargeOrder));
        }
    }

    public function getProxySettle(RechargeOrder $rechargeOrder)
    {
        $proxy_frozen = 0;
        if ($rechargeOrder->proxy) {
            $proxy_frozen = bcsub($rechargeOrder->proxy_settle, $rechargeOrder->order_settle, 6);
            $proxy_frozen = bccomp($proxy_frozen, 0, 6) > 0 ? $proxy_frozen : 0;
        }
        return $proxy_frozen;
    }

    public function getBusinessSettle(RechargeOrder $rechargeOrder)
    {
        $business_frozen = 0;
        if ($rechargeOrder->business) {
            $business_frozen = bcsub($rechargeOrder->business_settle, $rechargeOrder->order_settle, 6);
            $business_frozen = bccomp($business_frozen, 0, 6) > 0 ? $business_frozen : 0;
        }
        return $business_frozen;
    }


    public function checkQuerySign($data)
    {
        $user = PlatUser::bycode($data['mch_code'])->select('id', 'key')->first();
        $sign = $data['sign'];
        array_forget($data, 'sign');
        ksort($data);
        $signStr = '';
        foreach ($data as $k => $v) {
            $signStr .= "{$k}={$v}&";
        }
        $signStr .= $user->key;
        if (md5($signStr) == $sign) {
            return true;
        } else {
            return false;
        }
    }

}
